//
// Created by 12967 on 2022/1/12.
//

#ifndef DATASTRUCTURE_HASHLIST_H
#define DATASTRUCTURE_HASHLIST_H
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include "fileNode.h"
using namespace std;
class HashList;

struct HashListNode{
    HashListNode* next=NULL;
    string content;
    FileListNode* fileList=NULL;
};

struct IndexListNode{
    string content;
    HashListNode* wordList=new HashListNode;
    IndexListNode* next=NULL;
};




class HashList {
private:
    IndexListNode* indexHead;

public:
    HashList(){
        indexHead=new IndexListNode();
        indexHead->content="a";
        IndexListNode* iterator=indexHead;
        //a:97
        for(int i=1;i<=25;i++){
            iterator->next=new IndexListNode();
            iterator=iterator->next;
            iterator->content=(char)(i+97);
        }
    };


    void insert(string word,const string& fileName){
        IndexListNode* idxHead=this->indexHead;
        while(idxHead!=NULL){
            if(word[0]==idxHead->content[0]){
                HashListNode* wordIterator=idxHead->wordList;
                HashListNode* parentNode;
                while(wordIterator){
                    parentNode=wordIterator;
                    wordIterator=wordIterator->next;

                    if(wordIterator==NULL){
                        wordIterator=new HashListNode;
                        wordIterator->content=word;
                        parentNode->next=wordIterator;
                        wordIterator->fileList=new FileListNode;
                        wordIterator->fileList->file=fileName;
                        return;
                    }
                    else{
                        if(wordIterator->content==word){
                            FileListNode* fileIterator=wordIterator->fileList;
                            FileListNode* parent=NULL;
                            while(fileIterator){
                                if(fileIterator->file==fileName)
                                    return;
                                parent=fileIterator;
                                fileIterator=fileIterator->nextFile;
                            }

                            fileIterator=new FileListNode;
                            fileIterator->file=fileName;
                            if(parent!=NULL)//filelist为空的情况不需要parent
                                parent->nextFile=fileIterator;
                            return;
                        }
                    }
                }

            }idxHead=idxHead->next;
        }};

    void search(string targetWord,vector<string>& files,int* biop){
        IndexListNode* idxHead=this->indexHead;
        bool isfind=false;
        for(int i=0;i<files.size();i++){
            biop[i]=0;
        }
        while(true){
            if(targetWord[0]==idxHead->content[0]){
                HashListNode* wordIterator=idxHead->wordList->next;
                while(wordIterator!=NULL){
                    if(wordIterator->content==targetWord){
                        isfind=true;
                        FileListNode* fileIterator=wordIterator->fileList;
                        while(fileIterator){
                            auto iter=find(files.begin(),files.end(),fileIterator->file);
                            auto index=std::distance(files.begin(),iter);
                            biop[index]=1;
                            fileIterator=fileIterator->nextFile;
                        }cout<<endl;
                    }
                    if(wordIterator->next==NULL){
                        if(!isfind)
                            cout<<"NO MATCHED FILES!"<<endl;
                        return;
                    }
                    wordIterator=wordIterator->next;
                }
            }else{
                if(idxHead->next==NULL)
                    break;
                idxHead=idxHead->next;
            }
        }
        cout<<"NO MATCHED FILES!"<<endl;
    };

    void mutiSearch(vector<string> files){
        auto* command=new queue<string>;
        string s;
        while(cin>>s){
            if(s==",")
                break;
            command->push(s);
        }
        cout<<"WAIT A SEC......"<<endl;
        clock_t start,end;
        start=clock();
        int* result=new int[files.size()];
        this->search(command->front(),files,result);
        command->pop();
        while(!command->empty()){
            bool isOr=true;
            string op=command->front();
            if(op=="AND")
                isOr=false;
            command->pop();
            if(command->empty())
            {
                cout<<"SYNTAX ERROR!!!"<<endl;
                return;
            }else{
                int* result2=new int[files.size()];
                this->search(command->front(),files,result2);
                command->pop();
                if(isOr){
                    for(int i=0;i<files.size();i++){
                        result[i]=result[i]|result2[i];
                    }
                }else{
                    for(int i=0;i<files.size();i++){
                        result[i]=result[i]&result2[i];
                    }
                }

            }
        }
        bool noselected=true;
        cout<<"THE FINAL RESULT IS: "<<endl;
        for(int i=0;i<files.size();i++){
            if(result[i]){
                noselected=false;
                cout<<files[i]<<"\n ";
            }

        }
        if(noselected)
            cout<<"NO MATCHED FILES!!!";
        cout<<endl;
        end=clock();
        auto time=(double)(end-start)/CLOCKS_PER_SEC*1000;
        cout<<"Total time:"<<time<<"ms"<<endl;
    }

};

#endif //DATASTRUCTURE_HASHLIST_H
